package com.tyc.aqs;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * 借用aqs实现锁（只允许一个线程占用）
 * 独占式
 *  1. 返回true 成功获取结束
 *  2. 失败则加入队列
 *  3. 前一个节点为头节点且尝试获取成功，否则将节点排在非取消状态节点之后，并将前一个节点状态设置为signal,自己睡眠
 */
public class Mutex {

    private static class Sync extends AbstractQueuedSynchronizer{

        @Override
        protected boolean tryAcquire(int arg) {
            if(compareAndSetState(0,arg)){
                return true;
            }
            return false;
        }

        //因为只有一个线程能获取到锁，所以释放时不需要考虑线程安全问题
        @Override
        protected boolean tryRelease(int arg) {
            if(getState() == 0){
                throw new IllegalMonitorStateException();
            }
            setState(arg);
            setExclusiveOwnerThread(null);
            return true;
        }

        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }
    }
    private static final Sync sync = new Sync();
    public static void lock(){
        sync.acquire(1);
    }

    public static void unlock(){
        sync.release(0);
    }
}

class TestMutext{
    private static int num = 0;
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(10);
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
//                Mutex.lock();
                try {
                    ++num;
                    System.out.println(num);
                    countDownLatch.countDown();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
//                    Mutex.unlock();
                }
            }).start();
        }
        countDownLatch.await();
        System.out.println(num);
    }
}
